﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.ServiceLocation;
using Pap.Core.Utilities;
using Pap.Data;
using Pap.Data.Abstraction.Utils;
using Pap.Services;
using Pap.Services.WorkflowEngine;
using Pap.Web.Utils;

namespace Pap.Web.Modules.Loan.ViewModel
{
    /// <summary>
    /// 
    /// </summary>
    public class FeasibilityStudyViewModel : IViewModel
    {
        /// <summary>
        /// 
        /// </summary>
        ILoanRepository _LoanRepository;
        /// <summary>
        /// 
        /// </summary>
        IAdministrationRepository _AdmininstationRepository;
        /// <summary>
        /// 
        /// </summary>
        IWorkflowService _WfService;
        /// <summary>
        /// Initializes a new instance of the <see cref="FeasibilityStudyViewModel"/> class.
        /// </summary>
        /// <param name="loanRepo">The loan repo.</param>
        /// <param name="adminRepo">The admin repo.</param>
        /// <param name="wf">The wf.</param>
        public FeasibilityStudyViewModel(ILoanRepository loanRepo, IAdministrationRepository adminRepo, IWorkflowService wf)
        {
            this._LoanRepository = loanRepo;
            this._AdmininstationRepository = adminRepo;
            this._WfService = wf;
        }

        /// <summary>
        /// Gets all payment methods.
        /// </summary>
        /// <returns></returns>
        public ILoanPaymentMethod[] GetAllPaymentMethods()
        {
            var paymentMethods = _LoanRepository.FindLoanPaymentMethods(e => true);
            return paymentMethods.ToArray();
        }

        /// <summary>
        /// Gets the customer from loan.
        /// </summary>
        /// <param name="loanId">The loan id.</param>
        /// <returns></returns>
        public ICustomer GetCustomerFromLoan(string loanId)
        {
            Guid loanGuid = new Guid(loanId);
            ICustomerLoan loan = _LoanRepository.FindCustomerLoans(l => l.LoanID == loanGuid).FirstOrDefault();
            ICustomer customer = _LoanRepository.FindCustomers(c => c.CustomerID == loan.CustomerID).FirstOrDefault();
            return customer;
        }

        /// <summary>
        /// Gets the feasibility study for loan.
        /// </summary>
        /// <param name="loanId">The loan id.</param>
        /// <returns></returns>
        public ILoanFeasibilityStudy GetFeasibilityStudyForLoan(string loanId)
        {
            Guid loanGuid = new Guid(loanId);
            ILoanFeasibilityStudy study = _LoanRepository.FindLoanFeasibilityStudies(s => s.LoanID == loanGuid).FirstOrDefault();
            return study;
        }

        /// <summary>
        /// Gets the name of the payment method.
        /// </summary>
        /// <param name="paymentMethodId">The payment method id.</param>
        /// <returns></returns>
        public string GetPaymentMethodName(Guid paymentMethodId)
        {
            return _LoanRepository.GetLoanPaymentMethodByID(paymentMethodId).LoanPaymentMethodName;
        }

        /// <summary>
        /// Saves the feasibility study.
        /// </summary>
        /// <param name="loanID">The loan ID.</param>
        /// <param name="attachmentIDs">The attachment I ds.</param>
        /// <param name="deletedImages">The deleted images.</param>
        /// <param name="loanAmount">The loan amount.</param>
        /// <param name="paymentPeriod">The payment period.</param>
        /// <param name="totalIncome">The total income.</param>
        /// <param name="totalExpenses">The total expenses.</param>
        /// <param name="roi">The roi.</param>
        /// <param name="insallmentAmount">The insallment amount.</param>
        /// <param name="notes">The notes.</param>
        /// <param name="paymentMethodID">The payment method ID.</param>
        /// <param name="actionTaken">The action taken.</param>
        /// <param name="completionDate">The completion date.</param>
        public void SaveFeasibilityStudy(string loanID, IEnumerable<Guid> attachmentIDs, IEnumerable<Guid> deletedImages, string loanAmount, string paymentPeriod,
            string totalIncome, string totalExpenses, string roi,
            string insallmentAmount, string notes, string paymentMethodID, Pap.Services.WorkflowEngine.ActionTypes actionTaken,
            DateTime? completionDate)
        {
            using (IUnitOfWork unit = ServiceLocator.Current.GetInstance<IUnitOfWork>())
            {
                Guid loanGuid = new Guid(loanID);
                ILoanFeasibilityStudy study = _LoanRepository.FindLoanFeasibilityStudies(s => s.LoanID == loanGuid).FirstOrDefault();
                bool isNew = false;
                if (study == null)
                {
                    isNew = true;
                    study = ServiceLocator.Current.GetInstance<ILoanFeasibilityStudy>();
                    study.LoanFeasabilityStudyID = Guid.NewGuid();
                }
                study.CostAmount = double.Parse(totalExpenses);
                study.FeasabilityStudyDate = DateTime.Now;
                study.LoanAmount = double.Parse(loanAmount);
                study.LoanID = loanGuid;
                study.LoanPaymentMethodID = new Guid(paymentMethodID);
                study.LoanPaymentPeriod = int.Parse(paymentPeriod);
                study.Notes = notes;
                study.ReturnOnInvestmentPercent = decimal.Parse(roi);
                study.RevenueAmount = double.Parse(totalIncome);
                study.ProfitAmount = study.RevenueAmount - (study.CostAmount + (double)GetTaxValue());
                if (isNew)
                    _LoanRepository.CreateLoanFeasibilityStudy(study);

                // Move the workflow
                TakeDecision(loanID.ToGuid(), actionTaken, notes, completionDate);


                //Save Attachments
                foreach (var attachment in attachmentIDs)
                {
                    if (_LoanRepository.FindLoanFeasibilityStudyAttachments(a => a.Attachment == attachment && a.LoanFeasabilityStudyID == study.LoanFeasabilityStudyID).Count() == 0)
                    {
                        ILoanFeasibilityStudyAttachment att = this.GetInstance<ILoanFeasibilityStudyAttachment>();
                        att.LoanFeasabilityStudyAttachmentID = Guid.NewGuid();
                        att.LoanFeasabilityStudyID = study.LoanFeasabilityStudyID;
                        att.Attachment = attachment;
                        _LoanRepository.CreateLoanFeasibilityStudyAttachment(att);
                    }
                }

                foreach (var imageID in deletedImages)
                {
                    ILoanFeasibilityStudyAttachment att = _LoanRepository.FindLoanFeasibilityStudyAttachments(a => a.Attachment == imageID).FirstOrDefault();
                    if (att != null)
                    {
                        _LoanRepository.DeleteLoanFeasibilityStudyAttachment(att);
                    }
                }
                unit.Commit();
            }


        }
        /// <summary>
        /// Gets the tax value.
        /// </summary>
        /// <returns></returns>
        public decimal GetTaxValue()
        {
            return decimal.Parse(_AdmininstationRepository.GetSettingValue(RegistryInfo.CommitteeID, SettingKeys.FeasibilityStudyTaxes));
        }

        /// <summary>
        /// Takes the decision.
        /// </summary>
        /// <param name="loanID">The loan ID.</param>
        /// <param name="actionTaken">The action taken.</param>
        /// <param name="Notes">The notes.</param>
        /// <param name="completionDate">The completion date.</param>
        public void TakeDecision(Guid loanID, ActionTypes actionTaken, string Notes, DateTime? completionDate)
        {
            Guid processInstanceID = _WfService.GetProcessInstanceIDByEntity(loanID);
            _WfService.Move(actionTaken, processInstanceID, RegistryInfo.UserID, Notes, completionDate);
        }

        /// <summary>
        /// Gets the feasibility study images.
        /// </summary>
        /// <param name="studyID">The study ID.</param>
        /// <returns></returns>
        public IEnumerable<IImage> GetFeasibilityStudyImages(Guid studyID)
        {
            return _LoanRepository.FindLoanFeasibilityStudyAttachments(att => att.LoanFeasabilityStudyID == studyID).Select(study => study.AttachmentImage);
        }

        /// <summary>
        /// Determines whether [has social study] [the specified loan ID].
        /// </summary>
        /// <param name="LoanID">The loan ID.</param>
        /// <returns>
        ///   <c>true</c> if [has social study] [the specified loan ID]; otherwise, <c>false</c>.
        /// </returns>
        public bool HasSocialStudy(Guid LoanID)
        {
            var socialResearch = this._LoanRepository.FindLoanSocialResearches(lsr => lsr.LoanID == LoanID);
            if (socialResearch.Count() > 0)
                return true;
            else return false;
        }

        /// <summary>
        /// Gets the loan project.
        /// </summary>
        /// <param name="CurrentLoanID">The current loan ID.</param>
        /// <returns></returns>
        public IProjectStage GetLoanProject(string CurrentLoanID)
        {
            return this._LoanRepository.GetCustomerLoanByID(CurrentLoanID.ToGuid()).ProjectStage;
        }

        /// <summary>
        /// Gets the loan.
        /// </summary>
        /// <param name="CurrentLoanID">The current loan ID.</param>
        /// <returns></returns>
        public ICustomerLoan GetLoan(string CurrentLoanID)
        {
            return this._LoanRepository.GetCustomerLoanByID(CurrentLoanID.ToGuid());
        }

    }
}
